import type { ComponentStyleIdType } from '../../../types/interfaces'
import type { IUserData } from '../../../user_center/tab/personalization/custom_css/theme/others/greasy_fork/module/script_processor/types'
import { BaseModule } from '../../../lib/abstract'
import { PageHandler } from '../../../lib/page_handler'
import { GreasyForkPageType } from '../../../lib/page_handler/platform/greasyfork/types'
import {
  AppStyleCollections,
  ComponentStyleId,
  logger,
  PROJECT_PREFIX,
} from '../../../types/constants'
import { generateColorCycleSystem } from '../../../user_center/tab/personalization/custom_css/theme/common'
import { ConfigManager } from '../../config_manager'

export enum ChatDirectionType {
  LEFT = 'left',
  RIGHT = 'right',
}

export interface FloorMarkSelectors {
  /** 楼层容器选择器 */
  container: string
  /** 元数据选择器 */
  metaSelector: string
  /** 内容选择器 */
  contentSelector: string
  /** 用户链接元素选择器 */
  userLinkSelector: string
  /** 作者选择器 */
  authorSelector: string
  /** 当前用户id（标识当前登录用户） */
  currentUserId: string
  /** 楼主徽章插入目标选择器 */
  posterBadgeInsertTarget: string
  /** 用户 ID 提取函数 */
  extractUserId: (href: string) => string | null
  /** 标记插入目标选择器（空表示直接插入到容器） */
  markInsertTarget: string
}

interface Config {
  enabled?: boolean
}

export class FloorMarker extends BaseModule {
  // @Decorators.Identity
  readonly id: string = 'floor_mark'
  // @Decorators.PublicState
  isInitialized: boolean = false
  private static instance: FloorMarker
  // @Decorators.InheritedConfig
  readonly styleId: string = ComponentStyleId[this.name]
  readonly supportedPlatforms: string[] = ConfigManager.getInstance().moduleSupportedPlatforms(this.name)
  // @Decorators.Dependency
  private pageHandler: PageHandler = PageHandler.getInstance()
  // @Decorators.UIElement
  private readonly markerClass: string = 'floor-marker'
  private readonly containerClass: string = 'main-content'
  private readonly containerPadding: string = '15px'
  private readonly chatLeftClass: string = AppStyleCollections.Body.CHAT_LEFT
  private readonly chatRightClass: string = AppStyleCollections.Body.CHAT_RIGHT
  private readonly originalPosterClass: string = AppStyleCollections.Badge.ROLE_ORIGINAL_POSTER
  private readonly authorClass: string = AppStyleCollections.Badge.ROLE_AUTHOR
  private readonly mineClass: string = AppStyleCollections.Badge.ROLE_MINE

  config: Config = {
    enabled: true,
  }

  get name(): ComponentStyleIdType {
    return 'FloorMarker'
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): FloorMarker {
    if (!FloorMarker.instance) {
      FloorMarker.instance = new FloorMarker()
    }
    return FloorMarker.instance
  }

  destroy(): void {
    const { container, userLinkSelector } = this.getFloorSelectors()

    try {
      // 1. 移除所有创建的 DOM 元素
      $(`.${this.markerClass}`)?.remove()
      $(`.${AppStyleCollections.Body.AVATAR_CONTAINER}`)?.remove()

      // 2. 移除容器类
      $(container)
        ?.removeClass(this.chatLeftClass)
        .removeClass(this.chatRightClass)
        .removeClass(this.originalPosterClass)
        .removeClass(this.authorClass)
        .removeClass(this.mineClass)
        .find(userLinkSelector)
        ?.removeClass(AppStyleCollections.Hide.ELEMENT)

      // 3. 移除徽章
      $('.badge.badge-original-poster')?.remove()
      $('.badge.badge-mine')?.remove()

      // 4. 标记状态
      this.isInitialized = false

      // 5. 移除样式
      this.unregisterStyle(this.styleId)

      super.destroy()
    }
    catch (error: any) {
      logger.error(`[${this.name}] Error occurred during module destruction:`, error)
    }
  }

  core(): void {
    this.loadConfig()

    if (!this.config.enabled)
      return

    this.addFloorMarkers()

    // 注册样式
    this.registerStyle(this.styleId, this.getStyles())
  }

  onToggleCallback(_id: string, checked: boolean): void {
    super.onToggleCallback(_id, checked)
  }

  /**
   * 获取楼层标记的选择器配置
   */
  private getFloorSelectors(): FloorMarkSelectors {
    const pageType = this.pageHandler.services.greasyFork.pageType

    switch (pageType) {
      case GreasyForkPageType.SCRIPT_DISCUSSION:
        return {
          container: '#script-content > .comment',
          metaSelector: '.comment-meta',
          contentSelector: '.user-content',
          userLinkSelector: '.comment-meta .user-link',
          authorSelector: '.comment-meta .badge-author',
          currentUserId: this.pageHandler.services.greasyFork.getCurrentUserId(),
          posterBadgeInsertTarget: '.comment-meta-item-main',
          markInsertTarget: `.${this.containerClass}`,
          extractUserId: (href: string) => this.pageHandler.services.greasyFork.extractUserIdFromUrl(href),
        }
      case GreasyForkPageType.DISCUSSIONS_DETAIL:
        return {
          container: '.text-content > .comment',
          metaSelector: '.comment-meta',
          contentSelector: '.user-content',
          userLinkSelector: '.comment-meta .user-link',
          authorSelector: '',
          currentUserId: this.pageHandler.services.greasyFork.getCurrentUserId(),
          posterBadgeInsertTarget: '.comment-meta-item-main',
          markInsertTarget: `.${this.containerClass}`,
          extractUserId: (href: string) => this.pageHandler.services.greasyFork.extractUserIdFromUrl(href),
        }
      default:
        return {
          container: '',
          metaSelector: '',
          contentSelector: '',
          userLinkSelector: '',
          authorSelector: '',
          currentUserId: '',
          posterBadgeInsertTarget: '',
          markInsertTarget: `.${this.containerClass}`,
          extractUserId: () => null,
        }
    }
  }

  /**
   * 添加楼层标记
   */
  private addFloorMarkers() {
    let originalPosterId: string | null = null
    let lastUserId: string | null = null
    let lastUserStyle: ChatDirectionType | null = null
    const userSet = new Set<string>() // 用于记录所有用户ID
    const { container, userLinkSelector, authorSelector, currentUserId, posterBadgeInsertTarget, markInsertTarget, extractUserId } = this.getFloorSelectors()

    if (!container)
      return

    const $container = $(container)

    if (!$container || !$container.length)
      return

    // 首先找出楼主id（第一个id）
    $container.each((index, element) => {
      const $element = $(element)
      const $userLink = $element.find(userLinkSelector)
      const userId = extractUserId($userLink.attr('href') || '')

      if (userId) {
        userSet.add(userId)
        if (index === 0) {
          originalPosterId = userId // 记录第一个id
        }
      }
    })

    $container.each((index, element) => {
      const $item = $(element)
      const $userLink = $item.find(userLinkSelector)
      const userId = extractUserId($userLink.attr('href') || '')
      const floorNumber = index + 1

      // 避免重复添加
      if ($item.find(`.${this.markerClass}`).length > 0)
        return

      // 包裹评论内容
      const $containerElement = $item.find(`.${this.containerClass}`)
      if (!$containerElement || $containerElement.length === 0)
        $item.contents().wrapAll(`<div class="${this.containerClass}"></div>`)

      const $prependTarget = !markInsertTarget || markInsertTarget.length === 0 ? $item : $item.find(markInsertTarget)
      $prependTarget.prepend(`
        <div class="${this.markerClass}" title="第 ${floorNumber} 楼">
          #${floorNumber}
        </div>
      `)

      // 隐藏用户链接
      $userLink.addClass(AppStyleCollections.Hide.ELEMENT)

      // 添加用户头像
      const data: IUserData = {
        author: $userLink.text().trim(),
        authorUrl: $userLink.attr('href') || '',
      }
      this.pageHandler.features.user.addAvatar($item, data)

      if (userId) {
        if (userId && userId === originalPosterId) {
          if ($item.hasClass(this.originalPosterClass))
            return

          $item.addClass(this.originalPosterClass)
            .find(posterBadgeInsertTarget)
            .append(`<span class="badge badge-original-poster" title="本讨论的楼主">楼主</span>`)
        }
        else if (userId === currentUserId) {
          if ($item.hasClass(this.mineClass))
            return

          $item.addClass(this.mineClass)
            .find(posterBadgeInsertTarget)
            .append(`<span class="badge badge-mine" title="当前登录用户">我的</span>`)
        }
      }

      // 处理对话方向
      this.handleCommentDirection($item, userId, authorSelector, index + 1, lastUserId, lastUserStyle)

      // 更新最后记录的用户信息
      if (userId) {
        lastUserId = userId
        lastUserStyle = $item.hasClass(this.chatRightClass) ? ChatDirectionType.RIGHT : ChatDirectionType.LEFT
      }
    })

    // 只有一个评论或用户时，宽度取最大
    const shouldFullWidth = $container.length === 1 || userSet.size === 1
    if (shouldFullWidth) {
      $container.addClass(AppStyleCollections.Body.FULL_WIDTH)
    }
  }

  /**
   * 处理列表方向
   * @param $element 评论元素
   * @param userId 用户ID
   * @param authorSelector 作者选择器
   * @param index 当前索引
   * @param lastUserId 上一个用户ID
   * @param lastUserStyle 上一个用户样式
   */
  private handleCommentDirection(
    $element: JQuery<HTMLElement>,
    userId: string | null,
    authorSelector: string,
    index: number,
    lastUserId: string | null,
    lastUserStyle: ChatDirectionType | null,
  ): void {
    const isAuthor = $element.find(authorSelector).length > 0

    if (isAuthor) {
      // 作者评论始终使用偶数样式
      $element.addClass(`${this.authorClass} ${this.chatRightClass}`)
      return
    }

    if (!userId) {
      // 无法识别用户，回退到索引奇偶判断
      $element.addClass(index % 2 === 0 ? this.chatRightClass : this.chatLeftClass)
      return
    }

    if (userId === lastUserId && lastUserStyle) {
      // 同一用户连续评论，保持相同样式方向
      $element.addClass(lastUserStyle === ChatDirectionType.LEFT ? this.chatLeftClass : this.chatRightClass)
    }
    else {
      // 新用户，根据上一个用户决定样式
      $element.addClass(lastUserStyle === ChatDirectionType.LEFT ? this.chatRightClass : this.chatLeftClass)
    }
  }

  applyConfig(config: Partial<Config>): void {
    super.updateConfig(config)

    this.addFloorMarkers()

    logger.info(`[${this.name}] Config updated and apply`, this.config)
  }

  baseStyles(): string {
    return `
.${this.markerClass} {
  position: relative;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  color: white;
  font-weight: bold;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  margin-right: 5px;
}
`
  }

  getStyles(): string {
    const { container, metaSelector, contentSelector, posterBadgeInsertTarget, markInsertTarget } = this.getFloorSelectors()

    return `
${container} {
  position: relative;
  display: flex;
  align-items: flex-start;
  margin: 0 !important;
  padding: ${this.containerPadding} !important;
  background: var(${this.themeVarService.default.background.list}) !important;
  border-radius: 0 !important;
  transition: border-left-color 0.3s ease, box-shadow 0.3s ease !important;
  
  /* 内容区域 */
  .${this.containerClass} {
    grid-area: main;
    min-width: 0; /* 防止内容溢出 */
  }
  .floor-marker {
    grid-area: floor;
    min-width: 0; /* 防止内容溢出 */
  }
  ${metaSelector} {
    grid-area: meta;
    min-width: 0; /* 防止内容溢出 */
    border: none !important;
  }
  ${contentSelector} {
    grid-area: content;
    min-width: 0; /* 防止内容溢出 */
    border: none !important;
    background: transparent !important;
    word-break: break-word !important;
  }
  
  /* 对话样式 */
  &.${this.chatLeftClass} { /* 左侧 */
    .${this.containerClass} {
      --arrow-bg-color: var(--${PROJECT_PREFIX}-theme-discussion-bg-odd);
      
      box-shadow: var(--${PROJECT_PREFIX}-theme-discussion-shadow-odd) !important;
      border-top-left-radius: 0 !important;
      
      &::before {
        top: 9px;
        left: -16px;
        background: var(--arrow-bg-color);
        clip-path: polygon(100% 0, 0 50%, 100% 100%);
      }
    }
  }
  &.${this.chatRightClass} { /* 右侧 */
    flex-direction: row-reverse;
    
    .${this.containerClass} {
      --arrow-bg-color: var(--${PROJECT_PREFIX}-theme-discussion-bg-even);
      
      box-shadow: var(--${PROJECT_PREFIX}-theme-discussion-shadow-even) !important;
      border-top-right-radius: 0 !important;
      
      &::after {
        background: var(--arrow-bg-color);
        top: 9px;
        right: -16px;
        clip-path: polygon(0 0, 100% 50%, 0 100%);
      }
    }
  }
  
  /* 头像样式 */
  ${this.pageHandler.features.user.getAvatarStyles()}
  .${AppStyleCollections.Body.AVATAR_CONTAINER} {
    background: transparent !important;
    margin: 0 !important;
    padding: 0 !important;
  }
  
  .${this.containerClass} {
    position: relative !important;
    display: grid !important;
    grid-template-columns: auto 1fr;
    grid-template-rows: auto auto; /* 行数 */
    grid-template-areas:
      "floor meta"
      "content content";
    padding: 20px 20px 10px 20px !important;
    width: fit-content;
    max-width: 70%;
    min-width: 40%;
    background: var(--arrow-bg-color) !important;
    border-radius: 8px;
    
    &::before, &::after {
      content: '';
      position: absolute;
      width: 16px;
      height: 16px;
      z-index: 1;
    }
  }
  
  /* 特殊样式 */
  &.${this.mineClass} .${this.containerClass} {
    --arrow-bg-color: var(--${PROJECT_PREFIX}-theme-discussion-bg-mine);
  }
  &.${this.authorClass} .${this.containerClass} {
    --arrow-bg-color: var(--${PROJECT_PREFIX}-theme-discussion-bg-author);
  }
  &.${this.originalPosterClass} .${this.containerClass} {
    --arrow-bg-color: var(--${PROJECT_PREFIX}-theme-discussion-bg-original-poster);
  }
  
  /* 单条评论或用户时，宽度取最大 */
  &.${AppStyleCollections.Body.FULL_WIDTH} .${this.containerClass} {
    max-width: 100% !important;
    width: 100% !important;
  }

  ${markInsertTarget
      ? `
${markInsertTarget} {
    ${this.baseStyles()}
  }
  `
      : `${this.baseStyles()}`
  }
  
/* 楼层标识颜色样式 */
${generateColorCycleSystem(`.${this.markerClass}`)}

  ${posterBadgeInsertTarget} {
    display: flex !important;
    align-items: center !important;

    .badge {
      position: unset !important;
      display: inline-flex !important;
      align-items: center !important;
      white-space: nowrap; /* 禁止文本换行 */
      margin-left: 1ex !important;
      border-radius: 10% / 25% !important;
      height: 18px !important;
      font-size: 12px !important;
      padding: 1px 6px !important;
      text-transform: uppercase !important;
      
      /* 当前用户徽章样式 */
      &.badge-mine {
        background: linear-gradient(135deg, #9c27b0, #673ab7);
        color: white;
      }

      /* 楼主徽章样式 */
      &.badge-original-poster {
        background: linear-gradient(135deg, #ff9800, #ff5722);
        color: white;
      }
    }
  }
}
`
  }
}
